package net.tp.algo.graph;

import net.tp.util.Wrappers;

import java.util.List;

/**
 *
 * Common implementation shared between Digraph and UndirectedGraph.
 *
 * @see Digraph
 * @see UndirectedGraph
 *
 */
public abstract class BaseGraph implements Graph {

    protected List<Edge>[] nodes;

    @SuppressWarnings({"unchecked", "rawtypes"})
    public BaseGraph(int order) {
        this.nodes = new List[order];
    }

    @Override
    public int order() {
        return nodes.length;
    }

    @Override
    public Iterable<Integer> vertices() {
        return Wrappers.sequence(0, nodes.length);
    }

    @Override
    public Iterable<Integer> adjacents(int u) {
        return Wrappers.makeIterable(edges(u), (n) -> n.other(u));
    }

    @Override
    public Iterable<Edge> edges(int u) {
        return Wrappers.makeIterable(nodes[u]);
    }

    @Override
    public int degree(int u) {
        return nodes[u] != null ? nodes[u].size() : 0;
    }

    @Override
    public Iterable<Edge> edges() {
        return Wrappers.makeIterable(nodes);
    }


    public static class EdgeImpl implements Edge {

        private final int u;
        private final int w;
        private final double weight;
        private double flow;

        public EdgeImpl(int u, int w, double weight) {
            this.u = u;
            this.w = w;
            this.weight = weight;
        }

        @Override
        public int either() {
            return u;
        }

        @Override
        public int other(int v) {
            return this.u == v ? this.w : this.u;
        }

        @Override
        public double weight() {
            return weight;
        }

        @Override
        public double flow() {
            return flow;
        }

        @Override
        public void setFlow(double flow) {
            this.flow = flow;
        }

        @Override
        public String toString() {
            return String.format("%d-%d", u, w);
        }
    }
}
